/* JSDAS
* Copyright (C) 2008-2009 Bernat Gel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

//CODI DE http://www.devarticles.com/c/a/JavaScript/JavaScript-and-XML/1/
//Some code from jQuery

JSDAS.XMLLoader = {
	initialize: function() {
		this.initialized = true;
		this.proxyURL = 'proxy.php'; //TODO: this should be settable from the main jsDAS creation function
	},

	//Get a CORS-capable XHR or return null if not available
	xhrCORS: function(method, url) {
		var xhr;
		if(typeof XMLHttpRequest == "undefined"){ //We are at IE 6, return null since it doesn't support CORS
			return null;
		}
  		xhr = new XMLHttpRequest();
		if ("withCredentials" in xhr){ //check if the XMLHttpRequest object is CORS capable
		    xhr.open(method, url, true);
		} else if (typeof XDomainRequest != "undefined"){ //Try to get an IE specific CORS object
		    xhr = new XDomainRequest();
		    xhr.open(method, url);
		} else {
		    xhr = null;
		}
		return xhr;
	},

	// Create the request object; Microsoft failed to properly
	// implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
	xhr:function(){
		return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
	},
	/**This function loads an external XML using a proxy on the server to comply with the SOP
	 * 
	 * @param {Object} url
	 * @param {Object} callback
	 */
	load: function(url, callback, errorcallback){
		if (!this.initialized) {
			this.initialize();
		}
		var xmlloader = JSDAS.XMLLoader; //get a reference to myself
  
  
		var usingCORS = true;
		var xhr = this.xhrCORS('GET', url);
		if(!xhr) { //if the browser is not CORS capable, fallback to proxy if available
			if(this.proxyURL) {
			    var xhr = this.xhr();
			    xhr.open('GET', this.proxyURL+'?url='+url, true);
			    usingCORS = false;
			} else {
			    errorcallback && errorcallback({id: 'no_proxy', msg: "Cross-Origin requests are not supported but no proxy has been defined"});
			}
		}

		//At this point, we've got a valid XHR
		//xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
		//xhr.setRequestHeader("Accept", "application/xml, text/xml");


		var xmlloader = this; //necessary so the closures get the variable
		var change = function(xhr){
			if (xhr && (xhr.readyState == 4)) {
				if (xmlloader.httpSuccess(xhr)) {
					processResponse(xhr);
				}
				else { //if it failed, it mighht be that the source has no CORS enabled. In such case, fallback to proxy before erroring
					if(usingCORS && xmlloader.proxyURL) { //if it failed when using CORS and we've got a proxy, try to get the data via the proxy
					  xhr=undefined;
					  usingCORS = false;
					  var new_xhr = xmlloader.xhr();
					  new_xhr.open('GET', xmlloader.proxyURL+'?url='+url, true);
					  new_xhr.onreadystatechange = function() {change(new_xhr);}
					  new_xhr.send(null);
					} else {
					  errorcallback && errorcallback({id: "xmlhttprequest_error", msg: xhr.status});
					}
				}
				//to prevent IE memory leaks
				xhr = undefined;
			} 
		};
		var processResponse = function(xhr) {
			//WARNING: Since Uniprot (and maybe others) do not respond with a correct content-type, we cannot check it here. Should be reactivated as soon as the servers are updated.
			//var ct = xhr.getResponseHeader("content-type");
			//var xml = ct && ct.indexOf("xml") >= 0;
			//if (xml) {
				var data = xhr.responseXML;
				if(!data) { //This block is here since we cannot rely on content type headers
				     errorcallback && errorcallback({id: 'not_xml', msg: "The response was not XML"});
				}
				if(data.documentElement.nodeName != 'parsererror') {
					callback(data);
					return;
				} 
			//} //if anything went wrong, the document was not XML
			//errorcallback && errorcallback({id: 'not_xml', msg: "The response was not XML"});
		};
	
		xhr.onreadystatechange = function() {change(xhr);};

		// Send the data
		try {
			xhr.send(null);
		} catch(e) {
			//This code will rarely be called. Only when there's a problem on sernding the request.
			if(usingCORS && this.proxyURL) { //if it failed when using CORS and we've got a proxy, try to get the data via the proxy
			      var xhr = this.xhr();
			      xhr.open('GET', this.proxyURL+'?url='+url, true);
			      xhr.onreadystatechange = function() {change(xhr);}
			      try {
				  xhr.send(null);
			      } catch(e) {
				  errorcallback && errorcallback({id: 'sending_error', msg: "There was an error when sending the request"});
			      }
			} else {
			      errorcallback && errorcallback({id: 'sending_error', msg: "There was an error when sending the request"});
			}
		}	
	},
	httpSuccess: function( xhr ) {
		try {
			// IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
			return (!xhr.status && location.protocol == "file:" && xhr.responseXML) || //an empty responseXML with status=0 is possible with firefox using CORS from a file and failing because of the server
				( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223;
		} catch(e){}
		return false;
	}
};
